#!/usr/bin/perl
# 
#  Exercise 8.7 
# 
# For each codon, make note of what effect single nucleotide mutations have on the 
# codon: does the same amino acid result, or does the codon now encode a different 
# amino acid? Which one? Write a subroutine that, given a codon, returns a list of all 
# the amino acids that may result from any single mutation in the codon.
#
# Answer to Exercise 8.7

use strict;
use warnings;
use BeginPerlBioinfo;  # for subroutine "codon2aa"

#
# Get the user's codon
#
print "Input a codon: ";
my $codon = <STDIN>;
chomp $codon;

#
# Catch bad input
#
unless( codon2aa($codon)) {
	print "The codon \"$codon\" does not translate!\n";
	exit;
}

#
# Report results
#

print "The codon $codon translates to the amino acid: ", codon2aa($codon), "\n";

my @aa = codon_mutated_and_translated($codon);

print "A single mutation may result in the following amino acids: @aa\n";
exit;

##################################################
# Subroutines
##################################################

# The important subroutine as requested in the exercise

sub codon_mutated_and_translated {
	
	my($codon) = @_;

	my %translated_codons = ();

	my @mutated_codons = mutate_codons($codon);

	# A debugging print statement
	# print "The mutated codons are @mutated_codons\n";

	foreach my $mutated_codon (@mutated_codons) {

		# A debugging print statement
		# print "XX $mutated_codon -> ",codon2aa($mutated_codon),"\n";

		# This hash statement has the effect of defining each amino acid only once, so
		# the return statement for the subroutine doesn't give an amino acid twice if
		# there are two mutations that result in that amino acid.

		$translated_codons{codon2aa($mutated_codon)}++;
	}
	
	return keys %translated_codons;
}

#
# A helper subroutine: given a codon, it returns all the codons that
# can result from a single base change -- 9 in all.
#

sub mutate_codons {

	my($codon) = @_;

	my @bases = ('A','C','G','T');

	# To collect the output mutations
	my @mutations = ();
	
	#
	# Note the loop within a loop.  The outer loop loops through the 3 positions in the
	# codon.  The inner loop loops over the possible bases.
	#
	for(my $i = 0; $i < 3 ; ++$i) {
		foreach my $base (@bases) {

			my $mutation = $codon;

			if ($base eq substr($codon,$i,1)) {
				next;
			}else{
				substr($mutation,$i,1) = $base;
			}
			push(@mutations, $mutation)
		}
	}
	return @mutations;
}
